package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.entity.RoleResource;
import com.zzyl.entity.User;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.mapper.RoleResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.StringUtils;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 权限表服务实现类
 */
@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    RoleResourceMapper roleResourceMapper;

    /**
     * 多条件查询资源列表
     *
     * @param resourceDto
     * @return
     */
    @Override
    public List<ResourceVo> findResourceList(ResourceDto resourceDto) {
        List<Resource> resourceList = resourceMapper.selectList(resourceDto);
        return BeanUtil.copyToList(resourceList, ResourceVo.class);
    }

    @Override
    public TreeVo resourceTreeVo(ResourceDto resourceDto) {

        //构建查询条件
        ResourceDto dto = ResourceDto.builder().dataState(SuperConstant.DATA_STATE_0)
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .resourceType(SuperConstant.MENU)
                .build();

        //查询所有资源数据
        List<Resource> resourceList = resourceMapper.selectList(dto);
        if(EmptyUtil.isNullOrEmpty(resourceList)){
            throw new RuntimeException("资源信息未定义");
        }
        //没有根节点，构建根节点
        Resource rootResource = new Resource();
        rootResource.setResourceNo(SuperConstant.ROOT_PARENT_ID);
        rootResource.setResourceName("智慧养老院");

        //返回的树形集合
        List<TreeItemVo> itemVos = new ArrayList<>();

        //使用递归构建树形结构
        recursionTreeItem(itemVos,rootResource,resourceList);

        //数据返回
        return TreeVo.builder().items(itemVos).build();
    }


    /**
     * 使用递归构建树形结构
     * @param itemVos
     * @param rootResource
     * @param resourceList
     */
    private void recursionTreeItem(List<TreeItemVo> itemVos, Resource rootResource, List<Resource> resourceList) {
        //构建每个资源的属性
        TreeItemVo treeItemVo = TreeItemVo.builder()
                .id(rootResource.getResourceNo())
                .label(rootResource.getResourceName()).build();

        //获取当前资源下子资源
        List<Resource> childrenResourceList = resourceList.stream()
                .filter(n -> n.getParentResourceNo().equals(rootResource.getResourceNo()))
                .collect(Collectors.toList());
        //判断子资源是否为空
        if(!EmptyUtil.isNullOrEmpty(childrenResourceList)){

            List<TreeItemVo> listChildren = new ArrayList<>();
            //构建子资源
            childrenResourceList.forEach(resource -> {
                recursionTreeItem(listChildren,resource,resourceList);
            });
            treeItemVo.setChildren(listChildren);
        }

        itemVos.add(treeItemVo);
    }

    /**
     * 添加资源
     * @param resourceDto
     */
    @Override
    public void createResource(ResourceDto resourceDto) {
        //属性拷贝
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        //查询父资源
        Resource parenResource = resourceMapper.selectByResourceNo(resourceDto.getParentResourceNo());
        resource.setDataState(parenResource.getDataState());

        boolean isIgnore = true;
        //判断是否是按钮，如果是按钮，则不限制层级
        if(StringUtils.isNotEmpty(resourceDto.getResourceType())
                && resourceDto.getResourceType().equals(SuperConstant.BUTTON)){
            isIgnore=false;
        }
        //创建当前资源的编号
        String resourceNo = createResourceNo(resourceDto.getParentResourceNo(),isIgnore);
        resource.setResourceNo(resourceNo);

        resourceMapper.insert(resource);

    }

    @Override
    public void updateById(ResourceDto resourceDto) {
        //属性拷贝
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        Integer resout = resourceMapper.updateById(resource);
    }

    @Override
    public void updateStatus(ResourceDto vo) {
//        按钮绑定角色 不可禁用
        if ("1".equals(vo.getDataState())){
            RoleResource roleResource= new RoleResource();
            roleResource.setResourceNo(vo.getResourceNo());
            List<RoleResource> list = roleResourceMapper.list(roleResource);
            if (!list.isEmpty()){
                throw new BaseException(BasicEnum.BUTTON_DISTRIBUTED);
            }
        }else {
            if (!"100001000000000".equals(vo.getParentResourceNo())){
                Resource resource=resourceMapper.selectByResoureNo(vo.getParentResourceNo());
                if (resource!=null){
                    throw new BaseException(BasicEnum.PARENT_DEPT_DISABLE);
                }
            }
//        若父级菜单为禁用状态，点击子级菜单/按钮的【启用】按钮，出错误提示：父级菜单为禁用状态，不允许启用；
        }
        Resource resout = BeanUtil.toBean(vo, Resource.class);
        resourceMapper.updateStatus(resout);
    }

    @Override
    public void delete(String id) {
        Resource resource = resourceMapper.selectByResourceNo(id);
        if ("0".equals(resource.getDataState())){
            throw new BaseException(BasicEnum.MENU_DEL_EXCEPTION);
        }
        resourceMapper.deleteByResourceNo(id);
    }

    @Override
    public TreeVo getMenus() {
        System.out.println(UserThreadLocal.get());
        System.out.println(UserThreadLocal.getUserId());
        System.out.println(UserThreadLocal.getMgtUserId());
        System.out.println(UserThreadLocal.getSubject());

        return null;
    }

    /**
     * 根据用户id查询对应的资源数据
     * @param userId
     * @return
     */
    @Override
    public List<MenuVo> menus() {
        //查询用户对应的所有的菜单数据

        Long userId = UserThreadLocal.getMgtUserId();

        List<MenuVo> menuVoList = resourceMapper.findListByUserId(userId);
        if (CollUtil.isEmpty(menuVoList)) {
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
        }
        return menusTree(menuVoList);
    }

    @Override
    public List<MenuVo> myButten(Long id) {
        Long userId = UserThreadLocal.getMgtUserId();
        List<MenuVo> menuVoList = resourceMapper.findButtonByUserId(userId);
        if (CollUtil.isEmpty(menuVoList)) {
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
        }
        return menusTree(menuVoList);
    }

    /**
     * 创建资源的编号
     * @param parentResourceNo
     * @return
     */
    private String createResourceNo(String parentResourceNo,boolean isIgnore) {

        //判断资源编号是否大于三级
        //100 001 000 000 000
        //100 001 001 000 000
        //100 001 001 001 000
        //100 001 001 001 001 001
        if(isIgnore && NoProcessing.processString(parentResourceNo).length() / 3 >= 5){
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }

        //根据父资源编号查询子资源
        ResourceDto dto = ResourceDto.builder().parentResourceNo(parentResourceNo).build();
        List<Resource> resources = resourceMapper.selectList(dto);
        if(EmptyUtil.isNullOrEmpty(resources)){
            //无下属节点，创建新的节点编号  100 001 001 001 000--->100 001 001 001 001
            return NoProcessing.createNo(parentResourceNo,false);
        }else {
            //有下属节点，在已有的节点上追加
            //先获取已有节点的最大值--100001003000000
            Long maxNo = resources.stream().map(resource -> {
                return Long.valueOf(resource.getResourceNo());
            }).max(Comparator.comparing(i -> i)).get();

            return NoProcessing.createNo(String.valueOf(maxNo),true);
        }
    }

    public List<MenuVo> menusTree(List<MenuVo> menuVoList) {
        //数据进行分组（parentNo:[{},{}]）
        Map<String, List<MenuVo>> parentRNoMap = menuVoList
                .stream()
                .collect(Collectors.groupingBy(MenuVo::getParentResourceNo));
        //遍历所有数据
        menuVoList.forEach(menuVo -> {
            menuVo.setMeta(MenuMetaVo.builder().title(menuVo.getName()).build());
            menuVo.setRedirect("/"+menuVo.getName());
            //根据父编号到map中查找是否包含子菜单，如果包含则设置为当前菜单的子菜单
            List<MenuVo> menuVos = parentRNoMap.get(menuVo.getResourceNo());
            if(!EmptyUtil.isNullOrEmpty(menuVos)){
                menuVos.forEach(m->{
                    m.setMeta(MenuMetaVo.builder().title(menuVo.getName()).build());
                    m.setRedirect(m.getName());
                });
                menuVo.setChildren(menuVos);
            }
        });
        //根据根编号查找所有的子
        return parentRNoMap.get(SuperConstant.ROOT_PARENT_ID);
    }
}